﻿using System.Collections.Generic;
using System.Configuration;
using System.Data.Entity;
using System.Linq;
using System.Web;
using System.Web.Routing;
using ObjectModel;

namespace ViewServices
{
    public class ApplicationRoute : RouteBase
    {
        private readonly IRouteHandler _routeHandler;

        public ApplicationRoute(IRouteHandler routeHandler)
        {
            _routeHandler = routeHandler;
        }

        public override RouteData GetRouteData(HttpContextBase httpContext)
        {
            var routeData = new RouteData(this, _routeHandler);

            var virtualPath = httpContext.Request.AppRelativeCurrentExecutionFilePath.Substring(2) + httpContext.Request.PathInfo;

            if (virtualPath.Length > 100)
            {
                return null;
            }

            var pathSegments = virtualPath.Split(new[] { '/' });

            var applicationLink = pathSegments.Length == 0
                                         ? ConfigurationManager.AppSettings["defaultApplicationLink"]
                                         : pathSegments[0];

            using (var domainModel = new DataAccess.DomainModel())
            {
                var application = string.IsNullOrEmpty(applicationLink) ? domainModel.Applications.FirstOrDefault(a => a.IsDefault) : domainModel.Applications.FirstOrDefault(a => a.Link == applicationLink);

                if (application == null)
                {
                    return null;
                }

                routeData.Values["area"] = application.Area;
                routeData.Values["application"] = application.Name;
                routeData.Values["controller"] = application.Controller;
                routeData.Values["action"] = application.Action;

                var menuItem = pathSegments.Length < 2
                               ? application.MenuItems.FirstOrDefault(m => m.IsDefault)
                               : application.MenuItems.FirstOrDefault(m => m.Link == pathSegments[1]);

                if (menuItem != null)
                {
                    routeData.Values["action"] = menuItem.Action;
                    routeData.Values["menu"] = menuItem.Name;
                    return routeData;
                }

                if (pathSegments.Length >= 2)
                {
                    routeData.Values["action"] = pathSegments[1];

                    if (pathSegments.Length >= 3)
                    {
                        routeData.Values["id"] = pathSegments[2];

                        if (pathSegments.Length >= 4)
                        {
                            routeData.Values["page"] = pathSegments[3];
                        }
                    }
                }

                return routeData;
            }
        }

        public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
        {
            using (var domainModel = new DataAccess.DomainModel())
            {
                Application application;

                if (values.ContainsKey("application"))
                {
                    var applicationName = (string) values["application"];

                    application = domainModel.Applications.Where(a => a.Name == applicationName).Include(a => a.MenuItems).FirstOrDefault();
                }
                else
                {
                    if (!values.ContainsKey("controller"))
                    {
                        return null;
                    }

                    var controllerName = (string) values["controller"];

                    application = domainModel.Applications.Where(a => a.Controller == controllerName).Include(a => a.MenuItems).FirstOrDefault();
                }

                if (application == null)
                {
                    return null;
                }

                var parts = new List<string> {application.Link};

                if (values.ContainsKey("menu"))
                {
                    var menuName = (string) values["menu"];

                    var menuItem = application.MenuItems.FirstOrDefault(m => m.Name == menuName);

                    if (menuItem == null)
                    {
                        return null;
                    }

                    parts.Add(menuItem.Link);
                }
                else
                {
                    if (values.ContainsKey("action"))
                    {
                        parts.Add((string) values["action"]);

                        if (values.ContainsKey("id"))
                        {
                            parts.Add(values["id"].ToString());

                            if (values.ContainsKey("page"))
                            {
                                parts.Add(values["page"].ToString());
                            }
                        }
                    }
                }

                return new VirtualPathData(this, string.Join("/", parts));
            }
        }
    }
}